<template>
	<div class="page">
		<div id="3dcanvs"></div>
		<div
			class="btn"
			@click="
				animateCamera({ x: 0, y: 0, z: 0 }, { x: 100, y: 0, z: 10 })
			"
		>
			卧室
		</div>
		<div
			class="btn"
			@click="
				animateCamera({ x: 0, y: 0, z: 0 }, { x: 200, y: 0, z: 10 })
			"
		>
			客厅
		</div>
		<div
			v-for="(point, index) in roorms[0].interactivePoints"
			:key="index"
			:class="[`point-${point.key}`]"
		>
			<p class="p1">{{ point.value }}</p>
		</div>
	</div>
</template>

<script setup>
import { nextTick, onMounted, reactive } from "vue";
import * as THREE from "three";
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
// 引入tween动画库
import * as TWEEN from "@tweenjs/tween.js";

let roorms = reactive([
	{
		name: "客厅",
		interactivePoints: [
			{
				key: "tv",
				value: "电视",
				cover: "img/bg.png",
				position: new THREE.Vector3(-8, 2, -15),
			},
			{
				key: "art",
				value: "艺术品",
				cover: "img/bg2.png",
				position: new THREE.Vector3(10.5, 0, -15),
			},
		],
	},
]);
//设置场景宽高
const size = {
	width: window.innerWidth,
	height: window.innerHeight,
};
//场景
const scene = new THREE.Scene();
//相机
const camera = new THREE.PerspectiveCamera(
	75,
	size.width / size.height,
	0.1,
	1000
);
camera.position.set(10, 0, 0);
scene.add(camera);
//渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(size.width, size.height);
renderer.setClearColor(0x000000, 1); //设置背景颜色
renderer.setPixelRatio(window.devicePixelRatio); //设置 canvas 的像素比为当前设备的屏幕像素比，避免高分屏下出现模糊情况。

//创建多个房间以及环境贴图
//创建球体
let arr = ["img/bg.png", "img/bg2.png", "img/bg.png"];
for (let i = 0; i < 3; i++) {
	const sphereGeometry = new THREE.SphereGeometry(50, 50, 50);
	const textureLoader = new THREE.TextureLoader();
	const sphereMaterial = new THREE.MeshBasicMaterial({
		map: textureLoader.load(arr[i]),
		side: THREE.DoubleSide,
	});
	const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
	sphere.name = `sphere${i}`;
	sphere.position.set(0 + i * 100, 0, 0);
	sphere.geometry.scale(1, 1, -1);
	scene.add(sphere);
}

//设置相机移动漫游
//限制缩放

let controls = new OrbitControls(camera, renderer.domElement);
// 转动惯性（阻尼）
controls.enableDamping = true;
controls.dampingFactor = 0.1;
//设置缩放
controls.maxDistance = 5;

// const dir = new THREE.Vector3();
// // 获取相机的视线方向
// camera.getWorldDirection(dir);
//归一化后的向量 相当于 相机的位置减去相机的目标位置(position-lookAt)再进行归一化normalize()

function animateCamera(position, target) {
	let tween = new TWEEN.Tween({
		px: camera.position.x, // 起始相机位置x
		py: camera.position.y, // 起始相机位置y
		pz: camera.position.z, // 起始相机位置z
		tx: controls.target.x, // 控制点的中心点x 起始目标位置x
		ty: controls.target.y, // 控制点的中心点y 起始目标位置y
		tz: controls.target.z, // 控制点的中心点z 起始目标位置z
	});
	tween.to(
		{
			px: position.x,
			py: position.y,
			pz: position.z,
			tx: 100,
			ty: 100,
			tz: 100,
		},
		500
	);
	tween.to(
		{
			px: 100,
			py: 100,
			pz: 100,
			tx: target.x,
			ty: target.y,
			tz: target.z,
		},
		1000
	);
	tween.onUpdate(function () {
		camera.position.x = this._object.px;
		camera.position.y = this._object.py;
		camera.position.z = this._object.pz;
		controls.target.x = this._object.tx;
		controls.target.y = this._object.ty;
		controls.target.z = this._object.tz;
		controls.update();
	});
	tween.easing(TWEEN.Easing.Cubic.InOut);
	tween.start();
}

// 页面缩放事件监听
window.addEventListener("resize", () => {
	size.width = window.innerWidth;
	size.height = window.innerHeight;
	// 更新渲染
	renderer.setSize(size.width, size.height);
	renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
	// 更新相机
	camera.aspect = size.width / size.height;
	camera.updateProjectionMatrix();
});

// 渲染函数
function render() {
	controls && controls.update();
	TWEEN && TWEEN.update();
	renderer.render(scene, camera); //执行渲染操作
	requestAnimationFrame(render); //请求再次执行渲染函数render，渲染下一帧
}
render();

async function increment() {
	await nextTick();
	// DOM 此时已经更新
	document.getElementById("3dcanvs").appendChild(renderer.domElement);
}
onMounted(() => {
	increment();
});
</script>

<style lang="scss" scoped>
.page {
	& .btn {
		position: fixed;
		z-index: 100;
		right: 20px;
		top: 200px;
		background-color: #fff;
		font-size: 20px;
		border-radius: 10px;
		padding: 10px 20px;
		cursor: pointer;
	}

	& .btn:nth-of-type(2) {
		top: 300px;
	}

	& .point-tv {
		width: 200px;
	}
}
</style>
